package it.crosato.stage.shared.objects;

import java.util.Vector;

public class PetriNet {

	private Vector<String> S = new Vector<String>();
	private Vector<String> T = new Vector<String>();
	private int[][] I;
	private int[][] O;
	private int[][] A;

	/**
	 * Costruisce la rete di Petri relativa alla via metabolica in ingresso
	 * @param pathway la via metabolica di cui costruire la rete di Petri
	 */
	public PetriNet(Pathway pathway) {
		Vector<Reaction> reactions = new Vector<Reaction>();
		for (int i = 0; i < pathway.getReactions().size(); i++) {
			Reaction reaction = pathway.getReactions().get(i);
			T.add(reaction.getId());
			reactions.add(reaction);
			if (reaction.isReversible()) {
				Reaction reverse = reaction.getReverse();
				reactions.add(reverse);
				T.add(reverse.getId());
			}
		}
		S = pathway.getCompounds();
		setMatrices(reactions);
	}
	
	/**
	 * Setta le matrici di input, output e incidenza della rete di Petri.
	 * @param reactions l'insieme delle reazioni che compongono la via metabolica
	 */
	private void setMatrices(Vector<Reaction> reactions) {
		int n = S.size();
		int m = T.size();
		I = new int[n][m];
		O = new int[n][m];
		A = new int[n][m];
		for (int j = 0; j < m; j++) {
			Vector<ReactionElement> substrates = reactions.get(j).getSubstrates();
			Vector<ReactionElement> products = reactions.get(j).getProducts();
			for (int i = 0; i < n; i++) {
				boolean present = false;
				I[i][j] = 0;
				for (int k = 0; k < substrates.size() && !present; k++) {
					if (S.get(i).equals(substrates.get(k).getElementCode())) {
						I[i][j] = substrates.get(k).getStoichiometricFactor();
						present = true;
					}
				}
				present = false;
				O[i][j] = 0;
				for (int k = 0; k < products.size() && !present; k++) {
					if (S.get(i).equals(products.get(k).getElementCode())) {
						O[i][j] = products.get(k).getStoichiometricFactor();
						present = true;
					}
				}
				A[i][j] = O[i][j] - I[i][j];
			}
		}
	}
	
	public Vector<String> getS() {
		return S;
	}
	public void setS(Vector<String> s) {
		S = s;
	}
	
	public Vector<String> getT() {
		return T;
	}
	public void setT(Vector<String> t) {
		T = t;
	}

	public int[][] getI() {
		return I;
	}
	public void setI(int[][] i) {
		I = i;
	}
	
	public int[][] getO() {
		return O;
	}
	public void setO(int[][] o) {
		O = o;
	}
	
	public int[][] getA() {
		return A;
	}
	public void setA(int[][] a) {
		A = a;
	}
}
